package handler

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"internal/api/option"
	docs "internal/docs"
	"net/url"
	"strings"
)

// ApiEngine Api服务器引擎
type ApiEngine struct {
	Router        *gin.Engine            // 路由*gin.Engine引擎
	Ctx           *option.ServiceContext // 服务器启动配置
	AuthWhiteList map[string]string      // 鉴权白名单
}

// 私有全局变量
var httpSrv_ *ApiEngine

// InitHttpServer 初始化服务器方法(外部调用)
func InitHttpServer() {
	httpSrv_ = NewServer("0.0.0.0", 18890)
	if err := httpSrv_.Start(); err != nil {
		panic(err)
	}
}

// NewServer 实例化配置信息
func NewServer(host string, port int) *ApiEngine {
	// 实例化配置依赖
	o := option.Options{
		Host: host,
		Port: port,
	}
	ctx := option.NewServiceContext(o)
	// 设置gin模块,debug还是release
	gin.SetMode(gin.ReleaseMode)
	// 创建gin引擎
	// r := gin.Default() 默认使用gin自带
	// r := gin.Default()
	r := gin.New()
	// 使用gin自带中间件或者自己封装
	/*
		如果访问/panic,出现panic
		gin.Recovery()中间件会捕获这个panic，并且防止程序崩溃。它会记录下错误信息（通常是panic的值），并且向客户端返回一个500错误。
	*/
	r.Use(gin.Recovery(), GinLogger(), CorsMiddle())
	return &ApiEngine{
		Router:        r,
		Ctx:           ctx,
		AuthWhiteList: make(map[string]string),
	}
}

// Start 启动gin引擎
func (e *ApiEngine) Start() error {
	// 添加路由
	e.AddRoutes()

	// 添加鉴权白名单
	e.AddAuthWhiteList()

	// 启动服务
	bindAddress := fmt.Sprintf("%s:%d", e.Ctx.Config.Host, e.Ctx.Config.Port)
	if err := e.Router.Run(bindAddress); err != nil {
		return err
	}
	// 添加免鉴权白名单接口
	return nil
}

// WithInWhiteList 鉴权白名单列表
func (e *ApiEngine) WithInWhiteList(url *url.URL, method string) bool {
	// 请求url问号之前的
	queryUrl := strings.Split(fmt.Sprint(url), "?")[0]
	// 判断请求接口是否在添加白名单map里面
	value, ok := e.AuthWhiteList[queryUrl]
	if ok {
		if value == method {
			return true
		}
	}
	return false
}

// AddAuthWhite 添加白名单
func (e *ApiEngine) AddAuthWhite(url, method string) error {
	e.AuthWhiteList[url] = method
	return nil
}

// WithinWhiteList 实例化外部调用
func WithinWhiteList(url *url.URL, method string) bool {
	return httpSrv_.WithInWhiteList(url, method)
}

// AddRoutes 添加路由
func (e *ApiEngine) AddRoutes() error {
	docs.SwaggerInfo.BasePath = "/api/v1"
	// swapper 接口文档
	e.Router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
	// 添加静态文件
	e.Router.StaticFile("/favicon.ico", "./config/ favicon.ico")
	// 定义静态文件路径
	e.Router.Static("/image", "./view/image/")
	e.Router.Static("/js", "./view/js/")
	e.Router.Static("/css", "./view/css/")
	e.Router.GET("/index", GetStaticIndexHandler)
	// 返回首页静态文件
	e.Router.LoadHTMLFiles("./view/index.html")
	// 生成验证码
	e.Router.GET("/qrcode", GenerateQRCode)
	// 用户签到
	e.Router.GET("/account/signin", SignedHandler)
	// 用户注册
	e.Router.POST("/account/register", WrapHandlerV2(UserRegisterHandler))
	// 用户登录
	e.Router.POST("/account/login", WrapHandlerV2(UserLoginHandler))
	// 导出用户信息
	e.Router.GET("/account/get_list/export", UserInfoExportHandler)
	return nil
}

// AddAuthWhiteList 添加鉴权白名单列表
func (e *ApiEngine) AddAuthWhiteList() error {
	e.AddAuthWhite("/favicon.ico", "GET")
	e.AddAuthWhite("/ping", "GET")
	e.AddAuthWhite("/index", "GET")
	e.AddAuthWhite("/qrcode", "GET")
	e.AddAuthWhite("/css/style.css", "GET")
	e.AddAuthWhite("/js/script.js", "GET")
	e.AddAuthWhite("/image/bg.png", "GET")
	e.AddAuthWhite("/image/banner1.png", "GET")
	e.AddAuthWhite("/image/banner2.png", "GET")
	e.AddAuthWhite("/image/banner3.png", "GET")
	e.AddAuthWhite("/account/register", "POST")
	e.AddAuthWhite("/account/login", "POST")
	e.AddAuthWhite("/account/get_list/export", "GET")
	e.AddAuthWhite("/account/signin", "GET")
	return nil
}
